package com.rosca.converters.number2word.utils;

import java.util.Iterator;

/**
 * User: vrosca
 * Date: 7/27/11
 * Time: 1:03 PM
 * &copy; PFA Rosca Val Dan Dar Ion 2011
 * <p>
 * A class based on the Iterator pattern
 * that facilitates "scanning" a number
 * right-to-left for groups of digits of specified
 * digit count
 * An example for the number 1,514,271
 * </p>
 * <pre>
 *     int n = 1514271, idx = 0;
 *     for(int group : GroupScanner.scan(n, 3)){
 *         switch(idx++){
 *              case 0:
 *                  assert group == 271;
 *                  break;
 *              case 1:
 *                  assert group == 514;
 *                  break;
 *              case 2:
 *                  assert group == 1;
 *                  break;
 *              default:
 *                  throw new RuntimeException("Faulty");
 *         }
 *     }
 * </pre>
 */
public class GroupScanner implements Iterable<Integer> {
    /**
     * the number to scan
     */
    private int number;
    /**
     * how many digits are in a scanned group
     */
    private int digitCount;

    /**
     * Factory method creating an iterable group scanner
     *
     * @param number     the number to scan
     * @param digitCount how many digits should a group have
     * @return an iterable GroupScanner
     */
    public static GroupScanner scan(int number, int digitCount) {
        return new GroupScanner(number, digitCount);
    }

    protected GroupScanner(int number, int digitCount) {
        if (digitCount < 1)
            throw new IllegalArgumentException("Invalid group size specified");
        this.number = number;
        this.digitCount = digitCount;
    }

    /**
     * provides an iterator over the number's groups
     * taken from right to left and having the
     * specified digitCount
     *
     * @return iterator of group values
     */
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Integer current = number;
            boolean first = true;
            int mask = (int) Math.pow(10, digitCount);

            public boolean hasNext() {
                return current > 0 || first;
            }

            public Integer next() {
                int reminder = current % mask;
                current = current / mask;
                first = false;
                return reminder;
            }

            public void remove() {
            }
        };
    }
}
